home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  51.4 KB

  1. Subject:  v18i025:  Mail user's shell version 6.4, Part03/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 25
  8. Archive-name: mush6.4/part03
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 3 (of 19)."
  19. # Contents:  advanced.mushrc execute.c expr.c hdr_procs.c print.c
  20. #   rite.c sample.mushrc sort.c tool.c
  21. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:08 1989
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'advanced.mushrc' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'advanced.mushrc'\"
  25. else
  26. echo shar: Extracting \"'advanced.mushrc'\" \(4980 characters\)
  27. sed "s/^X//" >'advanced.mushrc' <<'END_OF_FILE'
  28. X# advanced.mushrc
  29. X# by Bart Schaefer
  30. X# with special thanks to Phil Lapsley <phil@east.Berkeley.EDU>, who
  31. X# provided the original files on which this example is based.  Most of
  32. X# Phil's stuff is still here -- just reorganized and updated to use
  33. X# mush 6.4 features that were unavailable when Phil did the originals.
  34. X#
  35. X# This file is intended to demonstrate helpful ways to use the
  36. X# .mushrc, not advanced mush commands.
  37. X
  38. X# The variable $thisfolder is always set EXCEPT when the .mushrc file
  39. X# is read the first time.  A test for non-existance of $thisfolder
  40. X# allows the same .mushrc file to be sourced repeatedly without
  41. X# redundant execution of the initialization commands.
  42. X#
  43. Xif ! $?thisfolder
  44. X    # Ignore the usual stuff
  45. X    ignore    received message-id status
  46. X    # Hide folders in ~/.mail and save read mail in spool
  47. X    set        folder=~/.mail hold
  48. X    # Remember a few commands, set up editors, act like a shell
  49. X    set        history=20 editor=ex visual=vi unix
  50. X    # Prompt has folder name, message number, history number
  51. X    set        prompt="%f %m (!) & "
  52. X    # Header summaries show name, date, and subject
  53. X    set        hdr_format="%25n %-15d  %27s"
  54. X    # Initialize the cmds below (see later comments)
  55. X    set        first_time=1
  56. X
  57. X    # These two commands are used for automated "bursting" of the spool
  58. X    # mailbox.  This means that the messages are reorganized into new
  59. X    # folders to be read in a prearranged order.  See comments below.
  60. X    #
  61. X    # n brings up the next folder, not the next message
  62. X    cmd        n    'source ~/.mushrc'
  63. X    # N gets the next folder without "bursting"
  64. X    cmd        N    'set first_time=0; source ~/.mushrc'
  65. X
  66. X    # Delete messages by pattern-matching.  Examples:
  67. X    #  del f mailer-daemon        Delete mail from mailer-daemon
  68. X    #  del t mush-users            Delete mail to mush-users
  69. X    cmd        del    'pick -i -\!* | delete'
  70. X    # Forwarding
  71. X    cmd        for    'mail -f'
  72. X    # Quick folder change
  73. X    cmd        F    'folder'
  74. X
  75. X    # Some useful aliases
  76. X    alias    dheller    'The Mush God <island\!argv@cad.berkeley.edu>'
  77. X    alias    barts    'Archangel Mushael <schaefer@cse.ogc.edu>'
  78. X
  79. X    # On init, don't source beyond this point
  80. X    exit
  81. Xendif    # End of init section -- read on startup only
  82. X
  83. X# This part of the file handles "bursting".  A burst is done when the
  84. X# n cmd is used the first time.  This is most useful if you habitually
  85. X# have lots of mail when you first log in each morning; unwanted mail
  86. X# can be deleted, and other mail organized for you.
  87. X#
  88. X# The folders in this example bursting scheme are:
  89. X#    mush-users    anything to or cc'ed to mush-users
  90. X#    stats        daily stats
  91. X#    root        root mail other than daily stats
  92. X# Mail not falling into one of these categories is left in the system
  93. X# mailbox to be dealt with first.
  94. X#
  95. Xif $first_time
  96. X    # Kill off some uucp garbage
  97. X    pick -i -s "file c.* delete" | delete
  98. X    pick -i -s "file .* can.t access" | delete
  99. X    pick -i -s "remote access to path/file denied" | delete
  100. X    # Nuke the boring usenet stuff
  101. X    pick -i -f usenet | pick -i -s "uucp map for" | delete
  102. X    pick -i -t usenet | pick -i -s "returned mail" | delete
  103. X    pick -i -t usenet | pick -i -s "automatic test echo" | delete
  104. X    pick -i -t "owner-post" | pick -i -s "unknown mailer" | delete
  105. X    pick -i -s "usenet disk space report" | delete
  106. X    pick -i -s "very old news articles" | delete
  107. X    pick -i -s "uucp map for" | delete
  108. X    # Wipe out some uninteresting daily stats
  109. X    pick -i -s "the maid was here." | delete
  110. X    pick -i -s "daily accounting" | delete
  111. X    pick -i -t netsurvey | delete
  112. X    # Get rid of these things for good.  This isn't essential, but
  113. X    # avoids complexity in the later "pick" commands.
  114. X    update
  115. X    # Save anything "to" or "cc" to mush-users in that folder.
  116. X    pick -i -t mush-users | save +mush-users
  117. X    pick -i -h cc mush-users | save +mush-users
  118. X    # Also save interesting daily stat mail and generic root mail
  119. X    pick -i -f root | pick -i -s stats | save +stats
  120. X    pick -i -f root | pick -i -s report | save +stats
  121. X    pick -i -f uucp | pick -i -s report | save +stats
  122. X    pick -i -f root | pick -i -s summary | save +stats
  123. X    pick -i -f root | pick -i -s munge | save +stats
  124. X    pick -i -t root | save +root
  125. X    # Again, make the changes permanent.  Saved mail gets deleted.
  126. X    # This won't work if you have $keepsave set.
  127. X    update
  128. X
  129. X    # Make sure we don't burst again needlessly.
  130. X    set first_time=0
  131. X
  132. X    # Stop sourcing here.  Otherwise, we'd change folders without
  133. X    # handling the mail left in the system mailbox.
  134. X    exit
  135. Xendif
  136. X
  137. X# Finally, handle stepping through the folders one by one.  This has been
  138. X# set up for sendmail, where the system mailbox is /usr/spool/mail/$USER,
  139. X# but could easily be modified for other mailers.
  140. X#
  141. X# $thisfolder:t returns the tail only of the folder name.
  142. X
  143. Xif $thisfolder:t == $USER
  144. X    folder +stats
  145. X    exit
  146. Xendif
  147. X
  148. Xif $thisfolder:t == stats
  149. X    folder +mush-users
  150. X    exit
  151. Xendif
  152. X
  153. Xif $thisfolder:t == mush-users
  154. X    folder +root
  155. X    exit
  156. Xendif
  157. X
  158. X# Default back to the system mailbox
  159. Xfolder %
  160. X
  161. X# End of advanced.mushrc
  162. END_OF_FILE
  163. if test 4980 -ne `wc -c <'advanced.mushrc'`; then
  164.     echo shar: \"'advanced.mushrc'\" unpacked with wrong size!
  165. fi
  166. # end of 'advanced.mushrc'
  167. fi
  168. if test -f 'execute.c' -a "${1}" != "-c" ; then 
  169.   echo shar: Will not clobber existing file \"'execute.c'\"
  170. else
  171. echo shar: Extracting \"'execute.c'\" \(5802 characters\)
  172. sed "s/^X//" >'execute.c' <<'END_OF_FILE'
  173. X/* execute.c     (c) copyright    10/28/86 (Dan Heller) */
  174. X
  175. X#include "mush.h"
  176. X#ifdef BSD
  177. X#include <sys/wait.h>
  178. X#else
  179. X#ifndef SYSV
  180. X#include <wait.h>
  181. X#endif /* SYSV */
  182. X#endif /* BSD */
  183. X
  184. X#ifdef lint
  185. X#include <sys/resource.h>
  186. X#endif /* lint */
  187. X
  188. Xexecute(argv)
  189. Xchar **argv;
  190. X{
  191. X#ifdef SYSV
  192. X    int status;
  193. X#else
  194. X    union wait status;
  195. X#endif /* SYSV */
  196. X#ifdef SIGCONT
  197. X    SIGRET (*oldstop)(), (*oldcont)();
  198. X#endif /* SIGCONT */
  199. X    int pid;
  200. X    SIGRET (*oldint)(), (*oldquit)();
  201. X
  202. X#ifdef SUNTOOL
  203. X    if (istool) {
  204. X    print("Editing letter...");
  205. X
  206. X    panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0);
  207. X    panel_set(send_item,  PANEL_SHOW_ITEM, FALSE, 0);
  208. X    panel_set(edit_item,  PANEL_SHOW_ITEM, FALSE, 0);
  209. X    win_setrect(tty_sw->ts_windowfd, &msg_rect);
  210. X    msg_rect.r_height = 0;
  211. X    win_setrect(msg_sw->ts_windowfd, &msg_rect);
  212. X    if ((exec_pid = ttysw_fork(tty_sw->ts_data, argv,
  213. X        &tty_sw->ts_io.tio_inputmask,
  214. X        &tty_sw->ts_io.tio_outputmask,
  215. X        &tty_sw->ts_io.tio_exceptmask)) == -1)
  216. X        error("%s failed", *argv), sigchldcatcher();
  217. X    Debug("tty pid = %d\n", exec_pid);
  218. X    return;
  219. X    }
  220. X#endif /* SUNTOOL */
  221. X    oldint = signal(SIGINT, SIG_IGN);
  222. X    oldquit = signal(SIGQUIT, SIG_IGN);
  223. X#ifdef SIGCONT
  224. X    oldstop = signal(SIGTSTP, SIG_DFL);
  225. X    oldcont = signal(SIGCONT, SIG_DFL);
  226. X#endif /* SIGCONT */
  227. X    turnon(glob_flags, IGN_SIGS);
  228. X
  229. X    echo_on();
  230. X    if ((exec_pid = vfork()) == 0) {
  231. X    (void) signal(SIGINT, SIG_DFL);
  232. X    (void) signal(SIGQUIT, SIG_DFL);
  233. X    (void) signal(SIGPIPE, SIG_DFL);
  234. X    (void) closefileds(3);    /* close all descriptors above 2 */
  235. X    execvp(*argv, argv);
  236. X    if (errno == ENOENT)
  237. X        print("%s: command not found.\n", *argv);
  238. X    else
  239. X        error(*argv);
  240. X    _exit(-1);
  241. X    }
  242. X    /* parent's got to do something; sigchldcatcher will do waiting
  243. X     * if other forks die (sendmail), then this wait will catch them,
  244. X     * This loop will really get -1, cuz sigchldcatcher will catch all else.
  245. X     */
  246. X    while ((pid = wait(&status)) != -1 && pid != exec_pid)
  247. X    Debug("The exec loop caught a signal? (pid = %d)\n", pid);
  248. X    /* reset our ttymodes */
  249. X    echo_off();
  250. X    (void) signal(SIGINT, oldint);
  251. X    (void) signal(SIGQUIT, oldquit);
  252. X#ifdef SIGCONT
  253. X    (void) signal(SIGTSTP, oldstop);
  254. X    (void) signal(SIGCONT, oldcont);
  255. X#endif /* SIGCONT */
  256. X    turnoff(glob_flags, IGN_SIGS);
  257. X}
  258. X
  259. XSIGRET
  260. Xsigchldcatcher()
  261. X{
  262. X#ifdef SUNTOOL
  263. X    struct rect rect;
  264. X    extern FILE *ed_fp;
  265. X#endif /* SUNTOOL */
  266. X#ifdef SYSV
  267. X    int status;
  268. X#else
  269. X    union wait status;
  270. X#endif /* SYSV */
  271. X    int       pid;
  272. X
  273. X#ifdef BSD
  274. X    /* The following SHOULDN'T be necessary, but it is!!! ttysw_fork()
  275. X     * returns the pid of the thing that it executes, but that's not the
  276. X     * pid that dies!  There are many procs that might die from ttysw_fork
  277. X     * one of them is the process, another is the tty, etc... other
  278. X     * procs that might die are sendmail, fortune, etc... tool_sigchld()
  279. X     * handles these, but we can't let it have control unless we KNOW the
  280. X     * editor is done.
  281. X     * so if what we catch is not the exec_pid from ttysw_fork(), then
  282. X     * send ourselves a sigchld to go thru this routine again.  mush -d
  283. X     */
  284. X    while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
  285. X    Debug("%d died...\n", pid);
  286. X    if (pid == exec_pid)
  287. X        break;
  288. X    }
  289. X#else
  290. X#ifndef SYSV
  291. X    while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid)
  292. X    Debug("%d died...\n", pid);
  293. X#else /* SYSV */
  294. X    while ((pid = wait((int *)0)) > 0 && pid != exec_pid)
  295. X    Debug("%d died...\n", pid);
  296. X#endif /* SYSV */
  297. X#endif /* BSD */
  298. X#ifndef SUNTOOL
  299. X    }
  300. X#else /* SUNTOOL */
  301. X    if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */
  302. X    return;
  303. X    /* editor died -- reset exec_pid so no one thinks we're running */
  304. X    exec_pid = 0;
  305. X    /* only the tool needs to continue from here.  Reset the win */
  306. X    if (istool < 1)
  307. X    return;
  308. X    tool_sigchld(tool);
  309. X    print("Editor done.");
  310. X    win_getrect(tty_sw->ts_windowfd, &msg_rect);
  311. X    if (msg_rect.r_height < 2 * l_height(curfont)) {
  312. X    print_more(" (well, something just happened)");
  313. X    return;
  314. X    }
  315. X    {
  316. X    extern char *edfile;
  317. X    if (!(ed_fp = fopen(edfile, "r+")))
  318. X        error("can't reopen %s", edfile);
  319. X    (void) fseek(ed_fp, 0L, 2);
  320. X    }
  321. X    /* I'd like to be able to just pw_rop the tty window onto the window
  322. X     * we're going to use now, but I can't access the data structure!
  323. X     *
  324. X     * pw_rop(msg_win, 0, 0, msg_rect.r_width, msg_rect.r_height, PIX_SRC,
  325. X     *        ((struct ??? *)(tty_sw->ts_data))->pr_pixrect, 0, 0);
  326. X     * So, instead, just clear the window and write the last N lines from the
  327. X     * end of the file into the window.
  328. X     */
  329. X    rect.r_top = rect.r_left = rect.r_height = 0;
  330. X    rect.r_width = msg_rect.r_width;
  331. X    win_setrect(tty_sw->ts_windowfd, &rect);
  332. X    win_setrect(msg_sw->ts_windowfd, &msg_rect);
  333. X    do_clear();
  334. X    /* read the last 2K bytes in the file -- search backwards for enough
  335. X     * carriage returns that will fill the window with the end of the letter
  336. X     * written so far and display the text.
  337. X     */
  338. X    {
  339. X    register long where = ftell(ed_fp);
  340. X    register int cr = 0, lines = msg_rect.r_height * l_height(curfont) - 3;
  341. X    char buf[2*BUFSIZ], *p;
  342. X    where = max(0, where-2*BUFSIZ);
  343. X    (void) fseek(ed_fp, where, L_SET);
  344. X    p = buf + read(fileno(ed_fp), buf, 2*BUFSIZ);
  345. X    *p = 0;
  346. X    while (cr < lines && p > buf)
  347. X        if (*--p == '\n')
  348. X        cr++;
  349. X    if (p > buf)
  350. X        while (*p != '\n')
  351. X        p++;
  352. X    Addstr(p);
  353. X    }
  354. X    panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0);
  355. X    panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
  356. X    panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
  357. X    panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0);
  358. X    wprint("(continue editing letter.)\n");
  359. X    type_cursor(PIX_SRC);
  360. X}
  361. X
  362. XSIGRET
  363. Xsigtermcatcher()
  364. X{
  365. X    ttysw_done(tty_sw->ts_data);
  366. X    if (ison(glob_flags, IS_GETTING))
  367. X    rm_edfile(-1);
  368. X    cleanup(SIGTERM);
  369. X}
  370. X#endif /* SUNTOOL */
  371. END_OF_FILE
  372. if test 5802 -ne `wc -c <'execute.c'`; then
  373.     echo shar: \"'execute.c'\" unpacked with wrong size!
  374. fi
  375. # end of 'execute.c'
  376. fi
  377. if test -f 'expr.c' -a "${1}" != "-c" ; then 
  378.   echo shar: Will not clobber existing file \"'expr.c'\"
  379. else
  380. echo shar: Extracting \"'expr.c'\" \(4682 characters\)
  381. sed "s/^X//" >'expr.c' <<'END_OF_FILE'
  382. X/* @(#)expr.c    2.3    (c) copyright 10/15/86 (Dan Heller) */
  383. X
  384. X#include "mush.h"
  385. X
  386. Xchar *eval_expr();
  387. X
  388. X/* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
  389. X * delimited by whitespace or comma's. Set msg_list bitfields using
  390. X * macros in mush.h.
  391. X * Return the address of the end of whatever we parsed (in case there's
  392. X * more that the calling routine cares to deal with).
  393. X * Finally, remember that user specifies one more than actual message number
  394. X */
  395. Xchar *
  396. Xdo_range(p, list1)
  397. Xregister char *p, *list1;
  398. X{
  399. X    register int num1 = -1, num2 = -1, except = 0;
  400. X    register char *p2;
  401. X    char list2[MAXMSGS_BITS];
  402. X
  403. X    if (!p)
  404. X    return "";
  405. X    while (*p) {
  406. X    if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
  407. X        if (isdigit(*p)) {
  408. X        char c;
  409. X        p2 = p;
  410. X        skipdigits(0);  /* find the end of the digits */
  411. X        c = *p, *p = 0; /* temporarily plug a null */
  412. X        if (!(num2 = chk_msg(p2))) {
  413. X            clear_msg_list(list1);
  414. X            return NULL;
  415. X        }
  416. X        *p = c;
  417. X        } else if (*p == '$')
  418. X        p++, num2 = msg_cnt;
  419. X        else if (*p == '.')
  420. X        p++, num2 = current_msg+1;
  421. X        else if (*p == '^')
  422. X        p++, num2 = 1;
  423. X        if (except)
  424. X        unset_msg_bit(list1, num2-1);
  425. X        else
  426. X        set_msg_bit(list1, num2-1);
  427. X        if (num1 >= 0) {
  428. X        if (num1 > num2) {
  429. X            print("syntax error: range sequence order reversed.\n");
  430. X            clear_msg_list(list1);
  431. X            return NULL;
  432. X        }
  433. X        while (++num1 < num2)
  434. X            if (except)
  435. X            unset_msg_bit(list1, num1-1);
  436. X            else
  437. X            set_msg_bit(list1, num1-1);
  438. X        num1 = num2 = -1;
  439. X        }
  440. X    }
  441. X    /* expressions to evaluate start with a `
  442. X     * p2 points to first char passed the last char parsed.
  443. X     */
  444. X    if (*p == '`') {
  445. X        clear_msg_list(list2);
  446. X        if (!(p = eval_expr(p, list2))) {
  447. X        clear_msg_list(list1);
  448. X        return NULL;
  449. X        } else {
  450. X        if (except)
  451. X            bitput(list2, list1, msg_cnt, &=~) /* MACRO */
  452. X        else
  453. X            bitput(list2, list1, msg_cnt, |=) /* MACRO */
  454. X        }
  455. X    }
  456. X    /* NOT operator: `* {5}' (everything except for 5)
  457. X     * `4-16 {8-10}'  (4 thru 16 except for 8,9,10)
  458. X     */
  459. X    if (*p == '{' || *p == '}') {
  460. X        if (*p == '{' && (except || num1 >= 0))
  461. X        break;
  462. X        if (*p == '}' && !except) {
  463. X        print("syntax error: missing {\n"); /* } */
  464. X        break;
  465. X        }
  466. X        except = !except;
  467. X    } else if (*p == '-')
  468. X        if (num1 >= 0 || num2 < 0
  469. X            || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
  470. X        break;
  471. X        else
  472. X        num1 = num2;
  473. X    else if (*p == ',' || *p == '*') {
  474. X        if (num1 >= 0)
  475. X        break;
  476. X        else if (*p == '*') {
  477. X        if (except)
  478. X            clear_msg_list(list1);
  479. X        else
  480. X            for (num1 = 0; num1 < msg_cnt; num1++)
  481. X            set_msg_bit(list1, num1);
  482. X        num1 = -1;
  483. X        }
  484. X    } else if (!index(" \t`", *p))
  485. X        break;
  486. X    if (*p)
  487. X        skipspaces(1); /* don't make user type stuff squished together */
  488. X    }
  489. X    if (num1 >= 0 || except) {
  490. X    if (except)
  491. X  /* { */   print("syntax error: unmatched }\n");
  492. X    else
  493. X        print("syntax error: unfinished range\n");
  494. X    clear_msg_list(list1);
  495. X    return NULL;
  496. X    }
  497. X    return p;
  498. X}
  499. X
  500. X/*
  501. X * convert a message list to an ascii string.
  502. X */
  503. Xvoid
  504. Xlist_to_str(list, str)
  505. Xchar list[], *str;
  506. X{
  507. X    int n, m = -1;
  508. X
  509. X    for (n = 0; n < msg_cnt; n++) {
  510. X    if (msg_bit(list, n)) {
  511. X        if (m == -1)
  512. X        str += strlen(sprintf(str, "%d", (m = n) + 1 ));
  513. X        continue;
  514. X    }
  515. X    if (m == -1)
  516. X        continue;
  517. X    if (n - m > 2)
  518. X        str += strlen(sprintf(str, "-%d", n));
  519. X    else if (n - m == 2)
  520. X        str += strlen(sprintf(str, " %d", n));
  521. X    *str++ = ' ';
  522. X    m = -1;
  523. X    }
  524. X    if (m > -1 && m != n - 1) {
  525. X    if (n - m > 2)
  526. X        *str++ = '-';
  527. X    else
  528. X        *str++ = ' ';
  529. X    str += Strcpy(str, itoa(msg_cnt));
  530. X    }
  531. X    *str = 0;
  532. X}
  533. X
  534. X/* evaluate expressions:
  535. X * mail> delete `pick -f root`     deletes all messages from root.
  536. X * mail> save * {`pick -s "Re:"`}  save all message that don't have "Re:"
  537. X *                   in the subject header.
  538. X * mail> save `pick -x -s "Re:"`   same
  539. X * args as follows:
  540. X *   p should point to the first ` -- check for it.
  541. X *   on tells whether to turn bits on or off if messages match.
  542. X */
  543. Xchar *
  544. Xeval_expr(p, new_list)
  545. Xregister char *p, new_list[];
  546. X{
  547. X    register char *p2, **argv;
  548. X    int       argc;
  549. X    u_long      save_flags = glob_flags;
  550. X
  551. X    if (!(p2 = index(++p, '`'))) {
  552. X    print("unmatched backquote (`)\n");
  553. X    return NULL;
  554. X    }
  555. X    *p2 = 0;
  556. X
  557. X    skipspaces(0);
  558. X    if (!*p) {
  559. X    print("Invalid null command\n");
  560. X    return NULL;
  561. X    }
  562. X    turnon(glob_flags, DO_PIPE);
  563. X    /* ignore sigs only because if user interrupts the do_command,
  564. X     * the longjmp will corrupt the stack and the program is hosed.
  565. X     * fix is to have layers of jmp_bufs to return to different levels.
  566. X     */
  567. X    turnon(glob_flags, IGN_SIGS);
  568. X    if (*p && (argv = make_command(p, TRPL_NULL, &argc)))
  569. X    (void) do_command(argc, argv, new_list);
  570. X    glob_flags = save_flags;
  571. X    *p2 = '`';
  572. X    return p2+1;
  573. X}
  574. END_OF_FILE
  575. if test 4682 -ne `wc -c <'expr.c'`; then
  576.     echo shar: \"'expr.c'\" unpacked with wrong size!
  577. fi
  578. # end of 'expr.c'
  579. fi
  580. if test -f 'hdr_procs.c' -a "${1}" != "-c" ; then 
  581.   echo shar: Will not clobber existing file \"'hdr_procs.c'\"
  582. else
  583. echo shar: Extracting \"'hdr_procs.c'\" \(4239 characters\)
  584. sed "s/^X//" >'hdr_procs.c' <<'END_OF_FILE'
  585. X/* @(#)hdr_procs.c    (c) copyright    10/18/86 (Dan Heller) */
  586. X
  587. X/* hdr_procs.c  -- panel item procedures for the message hdrs */
  588. X#include "mush.h"
  589. X
  590. X/* which message headers are to be displayed */
  591. Xdo_hdr(foo, value, event)
  592. XPanel_item foo;
  593. Xint value;
  594. Xstruct inputevent *event;
  595. X{
  596. X    register char *argv[3];
  597. X    argv[2] = NULL;
  598. X    argv[0] = "headers";
  599. X
  600. X    if (!msg_cnt) {
  601. X    print("No Mail.");
  602. X    return;
  603. X    }
  604. X    if (!value || event->ie_code == MS_LEFT)
  605. X    argv[1] = (foo == next_scr)? "+": "-";
  606. X    else
  607. X    argv[1] = (foo == next_scr)? "-": "+";
  608. X
  609. X    panel_set(foo, PANEL_VALUE, 0, 0);
  610. X    (void) do_hdrs(2, argv, NULL);
  611. X}
  612. X
  613. X/* alters display of the message headers */
  614. Xdisplay_hdrs(foo, value, event)
  615. XPanel_item foo;
  616. Xint value;
  617. Xstruct inputevent *event;
  618. X{
  619. X    int show_deleted = !!do_set(set_options, "show_deleted");
  620. X
  621. X    if (event->ie_code != MS_LEFT) {
  622. X    switch(value) {
  623. X        case 0 : case 1: {
  624. X        char buf[25];
  625. X        show_deleted = !value;
  626. X        (void) cmd_line(sprintf(buf, "%sset show_deleted",
  627. X            (value == 0)? "" : "un"), msg_list);
  628. X        }
  629. X        when 2 :
  630. X        turnoff(glob_flags, REV_VIDEO);
  631. X        when 3 :
  632. X        turnon(glob_flags, REV_VIDEO);
  633. X        when 4:
  634. X        return help(hdr_panel_sw->ts_windowfd, "headers", tool_help);
  635. X    }
  636. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  637. X    }
  638. X    print("%sShow Deleted headers, \"Current Message\" header in %s",
  639. X            (show_deleted)? NO_STRING: "Don't ",
  640. X            (ison(glob_flags, REV_VIDEO))? "reverse": "boldface");
  641. X}
  642. X
  643. Xp_set_opts(item, value, event)
  644. XPanel_item item;
  645. Xint value;
  646. Xstruct inputevent *event;
  647. X{
  648. X    static char   *p, *oldp;
  649. X    static char   buf[8];
  650. X    u_long bang = ison(glob_flags, IGN_BANG);
  651. X
  652. X    if (event->ie_code == MS_LEFT)
  653. X    value = 0;
  654. X    if (value && (value != 3 || value != 2)
  655. X          && panel_get(input_item, PANEL_SHOW_ITEM)) {
  656. X    print("Need value for %s first!", oldp);
  657. X    return;
  658. X    } else if (!value && ison(glob_flags, IS_GETTING)) {
  659. X    print("Finish editing letter first");
  660. X    return;
  661. X    } else if (item == option_item) {
  662. X    if (!value) /* first menu item */
  663. X        view_options();
  664. X    else if (value == 1)
  665. X        set_fkeys();
  666. X    else
  667. X        (void) help(panel_sw->ts_windowfd, "opts", tool_help);
  668. X    return;
  669. X    } else if (item == ignore_item)
  670. X    if (value == 3)
  671. X        return help(hdr_panel_sw->ts_windowfd, "ignore", tool_help);
  672. X    else
  673. X        oldp = p = strcpy(buf, "ignore");
  674. X    else if (item == alias_item)
  675. X    if (value == 3)
  676. X        return help(panel_sw->ts_windowfd, "aliases", tool_help);
  677. X    else
  678. X        oldp = p = strcpy(buf, "alias");
  679. X    if (value) {
  680. X    char tmp[30];
  681. X    (void) sprintf(tmp, "%set %s:", (value == 1)? "S": "Uns", p);
  682. X    panel_set(input_item,
  683. X        PANEL_LABEL_STRING, tmp,
  684. X        PANEL_MENU_CHOICE_STRINGS, "Abort", 0,
  685. X        PANEL_SHOW_ITEM, TRUE,
  686. X        0);
  687. X    oldp = p;
  688. X    return;
  689. X    }
  690. X    panel_set(item, PANEL_VALUE, 0, 0);
  691. X    do_clear();
  692. X    pw_text(msg_win, l_width(DEFAULT), 15, PIX_SRC, fonts[LARGE], p);
  693. X    if (item != ignore_item)
  694. X    pw_text(msg_win, 30*l_width(DEFAULT),15,PIX_SRC,fonts[LARGE],"Values");
  695. X    turnon(glob_flags, IGN_BANG);
  696. X    (void) cmd_line(p, msg_list);
  697. X    if (!bang)
  698. X    turnoff(glob_flags, IGN_BANG);
  699. X}
  700. X
  701. Xmsg_num_done(item, event)
  702. XPanel_item item;
  703. Xstruct inputevent *event;
  704. X{
  705. X    char buf[82];
  706. X    u_long bang = ison(glob_flags, IGN_BANG);
  707. X    register char *p;
  708. X    int n;
  709. X
  710. X    if (event->ie_code != '\n' && event->ie_code != '\r')
  711. X    return help(hdr_panel_sw->ts_windowfd, "message range", tool_help);
  712. X    (void) sprintf(buf, "headers %s", (p = (char *)panel_get_value(item)));
  713. X    panel_set(item, PANEL_VALUE, NO_STRING, 0);
  714. X    if (!(n = chk_msg(p)))
  715. X    return;
  716. X    current_msg = --n;
  717. X    turnon(glob_flags, IGN_BANG);
  718. X    (void) cmd_line(buf, msg_list);
  719. X    if (!bang)
  720. X    turnoff(glob_flags, IGN_BANG);
  721. X    display_msg(n, (long)0);
  722. X}
  723. X
  724. Xdo_sort(item, value, event)
  725. XPanel_item item;
  726. Xint value;
  727. Xstruct inputevent *event;
  728. X{
  729. X    register char *argv[3];
  730. X    argv[0] = "sort";
  731. X    argv[2] = NULL;
  732. X    if (event->ie_code == MS_LEFT)
  733. X    argv[1] = do_set(set_options, "sort");
  734. X    else switch(value) {
  735. X    case 0: argv[1] = "d";
  736. X    when 1: argv[1] = "a";
  737. X    when 2: argv[1] = "s";
  738. X    when 3: argv[1] = "S";
  739. X    when 4: argv[1] = "R";
  740. X    when 5: help(hdr_panel_sw->ts_windowfd, "sort", tool_help);
  741. X    }
  742. X    if (value != 5) {
  743. X    (void) sort(2, argv, NULL);
  744. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  745. X    }
  746. X    panel_set(item, PANEL_VALUE, 0, 0);
  747. X}
  748. END_OF_FILE
  749. if test 4239 -ne `wc -c <'hdr_procs.c'`; then
  750.     echo shar: \"'hdr_procs.c'\" unpacked with wrong size!
  751. fi
  752. # end of 'hdr_procs.c'
  753. fi
  754. if test -f 'print.c' -a "${1}" != "-c" ; then 
  755.   echo shar: Will not clobber existing file \"'print.c'\"
  756. else
  757. echo shar: Extracting \"'print.c'\" \(5250 characters\)
  758. sed "s/^X//" >'print.c' <<'END_OF_FILE'
  759. X/* @(#)print.c    2.4    (c) copyright 10/15/86 (Dan Heller) */
  760. X
  761. X#include "mush.h"
  762. X#include <varargs.h>
  763. X
  764. X/*ARGSUSED*/
  765. X/*VARARGS1*/
  766. Xvoid
  767. Xerror(fmt, arg1, arg2, arg3, arg4)
  768. Xregister char *fmt;
  769. Xchar *arg1, *arg2, *arg3, *arg4;
  770. X{
  771. X    print(fmt, arg1, arg2, arg3, arg4);
  772. X    print_more(": %s\n", sys_errlist[errno]);
  773. X}
  774. X
  775. X#if defined(SUNTOOL) || defined(CURSES)
  776. X/*
  777. X * print just like printf -- to a window, to curses, or to stdout.  Use vprintf
  778. X * if available.  msgbuf is the buffer used to print into if necessary.
  779. X * If you're running SUN3.2 or higher, the typecast (unsigned char *)msgbuf
  780. X * (where indicated) otherwise, msgbuf is not typecast at all.
  781. X * Also note same casting in wprint().
  782. X */
  783. X/*VARARGS*/
  784. Xvoid
  785. Xprint(va_alist)
  786. Xva_dcl
  787. X{
  788. X    static char msgbuf[BUFSIZ];
  789. X    char *fmt;
  790. X    va_list args;
  791. X#ifndef VPRINTF
  792. X    FILE foo;
  793. X#endif /* VPRINTF */
  794. X    static int x; /* position on line saved for continued prints */
  795. X    char *p; /* same type as struct file _ptr,_buf in stdio.h */
  796. X
  797. X#ifdef CURSES
  798. X    if (iscurses) {
  799. X    if (isoff(glob_flags, CONT_PRNT))
  800. X        move(LINES-1, x = 0), refresh();
  801. X    } else
  802. X#endif /* CURSES */
  803. X    if (istool < 2) {
  804. X        va_start(args);
  805. X        fmt = va_arg(args, char *);
  806. X#ifdef VPRINTF
  807. X        vprintf(fmt, args);
  808. X#else /* VPRINTF */
  809. X        _doprnt(fmt, args, stdout);
  810. X#endif /* VPRINTF */
  811. X        va_end(args);
  812. X        fflush(stdout);
  813. X        return;
  814. X    }
  815. X    va_start(args);
  816. X    fmt = va_arg(args, char *);
  817. X    if (fmt) {
  818. X#ifdef VPRINTF
  819. X    vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
  820. X#else /* VPRINTF */
  821. X    foo._cnt = BUFSIZ;
  822. X    foo._base = foo._ptr = msgbuf; /* may have to cast(unsigned char *) */
  823. X    foo._flag = _IOWRT+_IOSTRG;
  824. X    (void) _doprnt(fmt, args, &foo);
  825. X    *foo._ptr = '\0'; /* plant terminating null character */
  826. X#endif /* VPRINTF */
  827. X    }
  828. X    va_end(args);
  829. X    p = msgbuf;
  830. X    if (iscurses || istool)
  831. X    while (p = index(p, '\n'))
  832. X        *p = ' ';
  833. X#ifdef CURSES
  834. X    if (iscurses) {
  835. X    p = msgbuf;
  836. X    for (;;) {
  837. X        int len = COLS-1-x; /* space remaining at till the eol */
  838. X        /* don't wrap the line! Just print it and refresh() */
  839. X        printw("%-.*s", len, p), clrtoeol(), refresh();
  840. X        /* if length(p) (remainder of msgbuf) doesn't wrap, break loop */
  841. X        if ((x += strlen(p)) < COLS-1)
  842. X        break;
  843. X        /* the next print will overwrite bottom line, so \n first */
  844. X        putchar('\n'), move(LINES-1, x = 0); /* reset x */
  845. X        /* move p forward the number of chars we were able to display */
  846. X        p += len;
  847. X        turnon(glob_flags, CNTD_CMD); /* display ...continue... prompt */
  848. X    }
  849. X    turnoff(glob_flags, CONT_PRNT);
  850. X    fflush(stdout); /* some sys-v's aren't fflushing \n's */
  851. X    return;
  852. X    }
  853. X#endif /* CURSES */
  854. X#ifdef SUNTOOL
  855. X    if (isoff(glob_flags, CONT_PRNT))
  856. X    x = 5;
  857. X    turnoff(glob_flags, CONT_PRNT);
  858. X    pw_text(print_win, x,   l_height(LARGE), PIX_SRC, fonts[LARGE], msgbuf);
  859. X    pw_text(print_win, x+1, l_height(LARGE), PIX_SRC|PIX_DST,
  860. X               fonts[LARGE], msgbuf);
  861. X    x += strlen(msgbuf) * l_width(LARGE);
  862. X    Clrtoeol(print_win, x, l_height(LARGE), LARGE);
  863. X#endif /* SUNTOOL */
  864. X}
  865. X#endif /* SUNTOOL || CURSES */
  866. X
  867. X#ifdef SUNTOOL
  868. X/*VARARGS*/
  869. Xvoid
  870. Xwprint(va_alist)
  871. Xva_dcl
  872. X{
  873. X#ifndef VPRINTF
  874. X    FILE foo;
  875. X#endif /* VPRINTF */
  876. X    char msgbuf[BUFSIZ]; /* we're not getting huge strings */
  877. X    char *fmt;
  878. X    va_list args;
  879. X
  880. X    if (istool < 2) {
  881. X    va_start(args);
  882. X    fmt = va_arg(args, char *);
  883. X#ifdef VPRINTF
  884. X    vprintf(fmt, args);
  885. X#else /* VPRINTF */
  886. X    _doprnt(fmt, args, stdout);
  887. X#endif /* VPRINTF */
  888. X    va_end(args);
  889. X    fflush(stdout);
  890. X    return;
  891. X    }
  892. X    va_start(args);
  893. X    fmt = va_arg(args, char *);
  894. X    if (fmt) {
  895. X#ifdef VPRINTF
  896. X    vsprintf(msgbuf, fmt, args); /* NULL in fmt reprints last msg */
  897. X#else /* VPRINTF */
  898. X    foo._cnt = BUFSIZ;
  899. X    foo._base = foo._ptr = msgbuf; /* may have to cast (unsigned char *) */
  900. X    foo._flag = _IOWRT+_IOSTRG;
  901. X    _doprnt(fmt, args, &foo); /* format like printf into msgbuf via foo */
  902. X    *foo._ptr = '\0'; /* plant terminating null character */
  903. X#endif /* VPRINTF */
  904. X    Addstr(msgbuf);  /* addstr() will scroll if necessary */
  905. X    }
  906. X    va_end(args);
  907. X}
  908. X
  909. X/*
  910. X * scroll the msg_win "lines"
  911. X * if `lines' is negative (backwards scroll) msg_pix can't be NULL
  912. X */
  913. Xvoid
  914. Xscroll_win(lines)
  915. Xregister int lines;
  916. X{
  917. X    register int y = lines * l_height(curfont);
  918. X    /* if the user attempts to scroll back to before the beginning of the
  919. X     * message [either with the middle mouse button or the keyboard command
  920. X     * keys ('k', 'K', '-')], scroll back only to the beginning of the message.
  921. X     */
  922. X    if (txt.y + y < msg_rect.r_height)
  923. X    y = - (txt.y - msg_rect.r_height);
  924. X    txt.x = 5;
  925. X
  926. X    if (msg_pix) {
  927. X    if (txt.y + y >= msg_pix->pr_size.y - 5)
  928. X        y = msg_pix->pr_size.y - txt.y;
  929. X    still_more += y; /* let scrolling know where we are */
  930. X    txt.y += y;
  931. X    pw_rop(msg_win, 0, 5,
  932. X           msg_rect.r_width, crt * l_height(curfont),
  933. X           PIX_SRC, msg_pix, 0, txt.y - msg_rect.r_height + 3);
  934. X    tool_more(NULL);
  935. X    return;
  936. X    }
  937. X    /* y must be positive (forward scrolling) so we're scrolling typed
  938. X     * text or something like that (~p, ~?, etc...)
  939. X     */
  940. X    pw_copy(msg_win, 0, 0,
  941. X    msg_rect.r_width, msg_rect.r_height - y,
  942. X    PIX_SRC, msg_win, 0, y);
  943. X    pw_writebackground(msg_win, 0, msg_rect.r_height - y,
  944. X    msg_rect.r_width, y, PIX_CLR);
  945. X    txt.y -= y;
  946. X}
  947. X#endif /* SUNTOOL */
  948. X
  949. Xclr_bot_line()
  950. X{
  951. X    print("");
  952. X}
  953. END_OF_FILE
  954. if test 5250 -ne `wc -c <'print.c'`; then
  955.     echo shar: \"'print.c'\" unpacked with wrong size!
  956. fi
  957. # end of 'print.c'
  958. fi
  959. if test -f 'rite.c' -a "${1}" != "-c" ; then 
  960.   echo shar: Will not clobber existing file \"'rite.c'\"
  961. else
  962. echo shar: Extracting \"'rite.c'\" \(4181 characters\)
  963. sed "s/^X//" >'rite.c' <<'END_OF_FILE'
  964. X/* rite.c    (c) copyright 1986 (Dan Heller) */
  965. X
  966. X#include "mush.h"
  967. X
  968. X#define LASTLINE       (msg_rect.r_height - l_height(LARGE)-5)
  969. X
  970. Xstatic char String[BUFSIZ];
  971. Xstatic int count, overflow, save_orig_x;
  972. X
  973. Xchar *
  974. Xrite(c)
  975. Xregister char c;
  976. X{
  977. X    static int literal_next;
  978. X
  979. X    if (c == ltchars.t_lnextc || literal_next) {
  980. X    if (literal_next)
  981. X        Addch(c);
  982. X    else /* don't call Addch to prevent cursor from advancing */
  983. X        pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], '^');
  984. X    literal_next = !literal_next;
  985. X    return NULL;
  986. X    }
  987. X    literal_next = 0;
  988. X    if (c == _tty.sg_erase || c == CTRL(127) || c == CTRL(H)) {
  989. X    if (count)
  990. X        backspace();
  991. X    } else if (c == _tty.sg_kill) {
  992. X    if (count) {
  993. X        Clrtoeol(msg_win, txt.x = save_orig_x, txt.y,curfont);
  994. X        overflow = count = String[0] = 0;
  995. X    }
  996. X    } else if (c == ltchars.t_werasc)
  997. X    while (count) {
  998. X        char c = String[count-1];
  999. X        backspace();
  1000. X        if (!count ||
  1001. X        isspace(String[count-1]) && !isspace(c) ||
  1002. X        !isalnum(String[count-1]) && isalnum(c))
  1003. X        break;
  1004. X    }
  1005. X    else if (c == '\n' || c == '\r' || c == 13) {
  1006. X    String[count] = 0;
  1007. X    if ((txt.y += l_height(curfont)) >= LASTLINE && !getting_opts)
  1008. X        scroll_win(1);
  1009. X    /* else Clrtoeol(msg_win, txt.x, txt.y, curfont); */
  1010. X    overflow = count = 0, txt.x = 5;
  1011. X    return String;
  1012. X    } else if (c == 12)
  1013. X    if (ison(glob_flags, IS_GETTING))
  1014. X        Addch(c);
  1015. X    else
  1016. X        do_clear();
  1017. X    else if (count == BUFSIZ-1)
  1018. X    print("Text too long for String!"), count--;
  1019. X    else if (c == '\t')
  1020. X    do Addch(' ');
  1021. X    while (count % 8 && count < BUFSIZ);
  1022. X    else
  1023. X    Addch(c);
  1024. X    return NULL;
  1025. X}
  1026. X
  1027. Xstatic
  1028. Xbackspace()
  1029. X{
  1030. X    if (overflow) {
  1031. X    pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
  1032. X        &String[--overflow]);
  1033. X    Clrtoeol(msg_win, msg_rect.r_width-10-l_width(curfont), txt.y, curfont);
  1034. X    String[--count] = 0;
  1035. X    } else if ((txt.x -= l_width(curfont)) >= 5) {
  1036. X    if (iscntrl(String[count-1])) {
  1037. X        pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
  1038. X        txt.x -= l_width(curfont);
  1039. X    }
  1040. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
  1041. X    String[--count] = 0;
  1042. X    } else
  1043. X    txt.x = 5;
  1044. X}
  1045. X
  1046. Xstatic
  1047. XAddch(c)
  1048. Xregister char c;
  1049. X{
  1050. X    extern char *_unctrl[];
  1051. X
  1052. X    if (!count)
  1053. X    save_orig_x = txt.x, bzero(String, BUFSIZ);
  1054. X    if (c > 31 && c != 127)
  1055. X    String[count++] = c;
  1056. X    else {
  1057. X    Addch('^'), count--;
  1058. X    Addch(_unctrl[c][1]);
  1059. X    String[count-1] = c;
  1060. X    return;
  1061. X    }
  1062. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], c);
  1063. X    if ((txt.x += l_width(curfont)) <= msg_rect.r_width-5-l_width(curfont))
  1064. X    return;
  1065. X    if (getting_opts) {
  1066. X    pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
  1067. X        &String[++overflow]);
  1068. X    txt.x -= l_width(curfont);
  1069. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
  1070. X    } else {
  1071. X    txt.x = 5;
  1072. X    if ((txt.y += l_height(curfont)) >= LASTLINE)
  1073. X        scroll_win(1);
  1074. X    }
  1075. X}
  1076. X
  1077. XAddstr(s)
  1078. Xregister char *s;
  1079. X{
  1080. X    char buf[BUFSIZ];
  1081. X    register int cnt = 0, max_len;
  1082. X    register char *p = buf, newline = 0;
  1083. X
  1084. X    max_len = (msg_rect.r_width - 10) / l_width(curfont) + 1;
  1085. X
  1086. X    while ((*p = *s++) && *p != '\n' && cnt < max_len)
  1087. X    if (*p == '\t')
  1088. X        do *p++ = ' ';
  1089. X        while (++cnt % 8);
  1090. X    else p++, cnt++;
  1091. X    *p = 0;
  1092. X
  1093. X    if (*--s)
  1094. X    newline = *s, *s = 0; /* newline may or may not be a '\n' */
  1095. X    else
  1096. X    s = 0;
  1097. X
  1098. X    if (*buf) {
  1099. X    if (msg_pix) {
  1100. X        struct pr_prpos pixr;
  1101. X        pixr.pr = msg_pix;
  1102. X        pixr.pos = txt;
  1103. X        pf_text(pixr, PIX_SRC, fonts[curfont], buf);
  1104. X    } else
  1105. X        pw_text(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], buf);
  1106. X    txt.x += cnt * l_width(curfont);
  1107. X    }
  1108. X    if (newline) {
  1109. X    if (newline != '\n')
  1110. X        *s = newline;
  1111. X    if ((txt.y += l_height(curfont)) >= LASTLINE && !msg_pix)
  1112. X        scroll_win(1);
  1113. X    txt.x = 5;
  1114. X    if (newline == '\n' && !*++s)
  1115. X        return;
  1116. X    Addstr(s);
  1117. X    }
  1118. X}
  1119. X
  1120. Xtool_more(p)
  1121. Xregister char *p;
  1122. X{
  1123. X    int percent;
  1124. X    /* we are typing -- scrool the window */
  1125. X    if (!msg_pix) {
  1126. X    scroll_win(1);
  1127. X    return;
  1128. X    }
  1129. X    if (p)
  1130. X    print(p);
  1131. X    else {
  1132. X    if ((percent = (still_more * 100) / msg_pix->pr_size.y) >= 100)
  1133. X        print( "--End of Message %d--", current_msg+1);
  1134. X    else
  1135. X        print("--Message %d--(%d%%)", current_msg+1, percent);
  1136. X    if (ison(glob_flags, IS_GETTING))
  1137. X        print_more(" ('q' returns to type-in mode)");
  1138. X    }
  1139. X}
  1140. END_OF_FILE
  1141. if test 4181 -ne `wc -c <'rite.c'`; then
  1142.     echo shar: \"'rite.c'\" unpacked with wrong size!
  1143. fi
  1144. # end of 'rite.c'
  1145. fi
  1146. if test -f 'sample.mushrc' -a "${1}" != "-c" ; then 
  1147.   echo shar: Will not clobber existing file \"'sample.mushrc'\"
  1148. else
  1149. echo shar: Extracting \"'sample.mushrc'\" \(7468 characters\)
  1150. sed "s/^X//" >'sample.mushrc' <<'END_OF_FILE'
  1151. X# sample.mushrc
  1152. X# By Bart Schaefer and Dan Heller
  1153. X#
  1154. X# Change mush's temp file directory, to avoid quota collisions.
  1155. X# /usr/tmp so tmpfiles won't be rm'd before they can be recovered.
  1156. Xset tmpdir=/usr/tmp
  1157. X
  1158. X# Set the folder and mbox locations; the + expands to value of "folder".
  1159. Xset folder=$HOME/Mail mbox=+mbox
  1160. X
  1161. X# Set up the display early to allow quick exit in headers-only mode.
  1162. X# The hdrs_only flag is true if the command line was: "mush -H".
  1163. X# The variable hdr_format is set to change the format of the header
  1164. X# summaries that are displayed.
  1165. Xif hdrs_only
  1166. X    set hdr_format='%28a %M %-2N  %.33s'
  1167. X    exit    # Quits reading this file
  1168. Xelse
  1169. X    set hdr_format='%28a %M %-2N (%3.5l li) %.25s'
  1170. Xendif
  1171. X
  1172. X# Set the prompt to show current time, name of the current folder,
  1173. X# current message number, and count of total messages.
  1174. Xset prompt="(%T) %f: #%m of %t> "
  1175. X
  1176. X# Hitting <CR> should do nothing (helps make mush more shell-like).  If
  1177. X# newline is not set, hitting <CR> prints the next message (like Mail).
  1178. X# This variable could be set to any mush command.
  1179. Xset newline
  1180. X
  1181. X# These variables are helpful for new users:
  1182. X#    ask        -- always prompt for Subject: of mail
  1183. X#    ignoreeof    -- ignore end-of-file from keyboard
  1184. X#    verify        -- query that all is well before sending mail
  1185. X#    warning        -- report miscellaneous possible problems
  1186. Xset ask verify warning
  1187. Xset ignoreeof="echo 'Use "'"'quit'"'" to quit.'"
  1188. X
  1189. X# When reading messages, don't bother looking at lengthy, boring headers.
  1190. Xignore message-id received
  1191. X
  1192. X# Since mush has csh-like history, you might find it annoying to type
  1193. X# things like "mail host\!host1\!host2\!user" from within the mush shell.
  1194. X# Setting nonobang will prevent the "unknown event" and allow the !'s to
  1195. X# be typed without having to be preceded by backslashes.
  1196. Xset nonobang
  1197. X
  1198. X# By default, mush's history is set to the last command only.  Set it to
  1199. X# remember the last 100 commands.
  1200. Xset history = 100
  1201. X
  1202. X# If the variable "unix" is set, then any command that isn't a mush command
  1203. X# will execute the command as if you typed it from the shell.  Note, such
  1204. X# commands will not go through another shell -- this is it.
  1205. Xset unix
  1206. X
  1207. X# Mush tries to read ~/.mushrc first, then it tries ~/.mailrc.  Assuming
  1208. X# you use *this* file as your .mushrc, source the contents of .mailrc as
  1209. X# well in case there are Mail aliases that are set there.
  1210. Xsource $HOME/.mailrc
  1211. X
  1212. X# Use a real pager.
  1213. Xset pager=less
  1214. X
  1215. X# When typing in a letter, it is sometimes convenient to have lines wrap
  1216. X# automatically similar to editors like vi and emacs.  In this example, if
  1217. X# the user types past column 74, a newline will automatically be inserted.
  1218. Xset wrapcolumn=74
  1219. X
  1220. X# If "autosign" is set, then a file can be read in automatically whenever
  1221. X# mail is sent.  This file is normally your "signature," that is, your
  1222. X# name and other information you want included in every message.
  1223. Xset autosign = ~/.signature
  1224. X
  1225. X# When you use the -i option to reply, or use the ~i tilde escape in a letter
  1226. X# when in compose mode, the current message will be included in your text.
  1227. X# Put a nice wrapper around those included messages.  Here, show the author's
  1228. X# name and the subject of his letter, label the end, and add a trailing blank
  1229. X# to separate each inclusion and make finding the end easier.
  1230. Xset pre_indent_str='On %M %N, %T, %.50n wrote:\n} Subject: %.65s'
  1231. Xset indent_str='} '    # actual message text is preceded by a "}"
  1232. Xset post_indent_str='}-- End of excerpt from %.50n\n'
  1233. X
  1234. X# Label replies with a header showing the who, what, and when of the
  1235. X# message being replied-to.
  1236. Xset in_reply_to='%f\n\t"%s" (%d)'
  1237. X
  1238. X# Mail routing and address-fixing conveniences.  If auto_route is set, then
  1239. X# replies to messages take a closer look at the addresses of the recipients.
  1240. X# If any redundant paths are present, they are pruned.  Also, the path that
  1241. X# precedes any hosts listed in the "known_hosts" list is truncated.  This is
  1242. X# useful for uucp sites only, and is therefore commented out in this sample.
  1243. X# set auto_route known_hosts="sun ucbcad well unicom"
  1244. X
  1245. X# The "alts" command specifies alternate addresses that I have.  Here,
  1246. X# "*" expands to any "path" whose recipient ends with the user's current
  1247. X# login name.  If another login name is desired, the login and/or path
  1248. X# to that login must be preceded by a !.  Otherwise, standard paths are used.
  1249. Xalts "*"
  1250. X
  1251. X# The "map" command can rebind certain key sequences in tty-mode only.
  1252. X# Here, if the user types two R's in a row at the prompt, then the string
  1253. X# "reply -ei " will be echoed as if the user typed it.
  1254. Xmap RR "reply -ei "
  1255. X# "rr" will do a reply and do the newline for you so you don't have to.
  1256. Xmap rr "reply\n"
  1257. X
  1258. X# The "map!" command is similar to "map" in that you can do keyboard
  1259. X# acceleration, but map! occurs during letter composition mode only.
  1260. Xmap! '\CT' '    '    # ^T generates 4 spaces in composition mode.
  1261. X# Here, hitting * twice will append a pre-signature.
  1262. Xmap! ** "\n            Later,\n"
  1263. X
  1264. X# Be careful with map and map! -- you can cause an infinite loop.
  1265. X# Your interrupt key (usually ^C) will stop such loops.
  1266. X
  1267. X# The curses mode allows the screen to be set up like a full screen editor.
  1268. X# There are basic "curses commands" which are bound to keyboard key-sequences
  1269. X# (usually one character).  The user can rebind these keys to suit his tastes.
  1270. X# Note that the binding for R below removes the binding of reply-all.
  1271. X#
  1272. Xset curses_help        # Unset this to remove help message in curses.
  1273. Xbind \n display        # Hit return to display the next message.
  1274. Xbind t top        # Make it easier to see the top few lines.
  1275. Xbind e macro "[line-mode]edit\n"    # Quick edit from curses.
  1276. Xbind P macro "[line-mode]Print\n"    # Show me all the headers.
  1277. Xbind R macro "[line-mode]reply -ei "    # Reply with inclusion and edit.
  1278. Xbind A macro "R[getline]~t\n\CUargv\n"    # R to Dan w/auto address fix.
  1279. X
  1280. X# "cmd" is used to set command line aliases similar to the way "csh"
  1281. X# does it.  The only difference is that "alias" is a reserved word in
  1282. X# Mush and Mail, so cmd is used.
  1283. X#
  1284. Xcmd dq 'd \!*; q'        # Delete a message list, then quit.
  1285. Xcmd unread 'flags \!* U O'    # Mark messages unread.
  1286. Xcmd : curses            # Colon now "toggles" curses mode.
  1287. X
  1288. X# Find messages from mailer-daemon (ignore upper/lower case).
  1289. Xcmd md 'pick -i -f mailer-daemon'
  1290. X# Because mush can pipe commands to one another, including "cmd"'s, this
  1291. X# example will delete all messages from mailer-daemon
  1292. Xcmd dmd 'md | delete'
  1293. X
  1294. X# aliases -- just like Mail's, but you can specify "names"
  1295. Xalias argv Dan Heller <island!argv@sun.com>
  1296. Xalias bart Bart Schaefer <schaefer@ogccse.ogc.edu>
  1297. Xalias mush-users Mush Users <mush-users-request@garp.mit.edu>
  1298. X
  1299. X# The rest of this file demonstrates how sysadmins with novice users
  1300. X# might want to set things up.  The following "exit" should be removed.
  1301. Xexit
  1302. X
  1303. Xif -e $HOME/.mushexpert
  1304. X    set quiet
  1305. X    exit
  1306. Xendif
  1307. Xif ! -e $HOME/.mushuser
  1308. X    echo "I see you've never used the Mush program before."
  1309. X    echo "I'll set some special flags to help you out."
  1310. X    echo "After you've used Mush a few times, you can type the command:"
  1311. X    echo -p "${prompt} expert\n"
  1312. X    echo "and the flags will no longer be set unless you put them"
  1313. X    echo "in your $HOME/.mushrc file."
  1314. X    sh touch $HOME/.mushuser    # Use sh in case $unix is not set.
  1315. X    if $?quiet
  1316. X    unset quiet        # Show the help message on startup.
  1317. X    endif
  1318. Xendif
  1319. X# At this point some helpful variables should be set.  See the list above,
  1320. X# marked as "helpful for new users", for suggestions.
  1321. X#
  1322. X# Create the "expert" command mentioned in the message above.
  1323. Xcmd expert 'sh touch $HOME/.mushexpert'
  1324. END_OF_FILE
  1325. if test 7468 -ne `wc -c <'sample.mushrc'`; then
  1326.     echo shar: \"'sample.mushrc'\" unpacked with wrong size!
  1327. fi
  1328. # end of 'sample.mushrc'
  1329. fi
  1330. if test -f 'sort.c' -a "${1}" != "-c" ; then 
  1331.   echo shar: Will not clobber existing file \"'sort.c'\"
  1332. else
  1333. echo shar: Extracting \"'sort.c'\" \(5803 characters\)
  1334. sed "s/^X//" >'sort.c' <<'END_OF_FILE'
  1335. X/* sort.c 2.0    (c) copyright 1986 (Dan Heller) */
  1336. X
  1337. X#include "mush.h"
  1338. X/* #define MYQSORT */
  1339. X
  1340. Xstatic int order, ignore_case;
  1341. Xstatic jmp_buf sortbuf;
  1342. X
  1343. Xsort(argc, argv, list)
  1344. Xregister int argc;
  1345. Xregister char *argv[], list[];
  1346. X{
  1347. X    int status_cmp(), author_cmp(), date_cmp(), subject_cmp(), subj_with_re();
  1348. X    SIGRET (*oldint)(), (*oldquit)();
  1349. X    int (*how)() = status_cmp;
  1350. X    int n, offset = -1, range = 0;
  1351. X
  1352. X    order = 1, ignore_case = FALSE;
  1353. X
  1354. X    while (argc && *++argv) {
  1355. X    n = 0;
  1356. X    while (argv[0][n])
  1357. X        switch(argv[0][n++]) {
  1358. X        case '-': order = -1;
  1359. X        when 'd': how = date_cmp;
  1360. X        when 'a': how = author_cmp;
  1361. X        when 's': how = subject_cmp;
  1362. X        when 'R': how = subj_with_re;
  1363. X        when 'S': how = status_cmp;
  1364. X        when 'i': ignore_case = TRUE;
  1365. X        otherwise: return help(0, "sort", cmd_help);
  1366. X        }
  1367. X    }
  1368. X    if (msg_cnt <= 1) {
  1369. X    print("Not enough messages to sort.\n");
  1370. X    return -1;
  1371. X    }
  1372. X    turnon(glob_flags, IGN_SIGS);
  1373. X    on_intr();
  1374. X
  1375. X    if (list && ison(glob_flags, IS_PIPE)) {
  1376. X    for (n = 0; n < msg_cnt; n++)
  1377. X        if (msg_bit(list, n)) {
  1378. X        if (offset < 0)
  1379. X            offset = n;
  1380. X        range++;
  1381. X        } else if (offset >= 0)
  1382. X        break;
  1383. X    } else
  1384. X    offset = 0, range = msg_cnt;
  1385. X
  1386. X    if (range < 2)
  1387. X    print("Range not broad enough to sort anything\n");
  1388. X    else {
  1389. X    Debug("Sorting %d messages starting at message %d\n", range, offset+1);
  1390. X
  1391. X    if (setjmp(sortbuf) == 0)
  1392. X        qsort((char *)&msg[offset], range, sizeof (struct msg), how);
  1393. X    else
  1394. X        print("WARNING: Sorting interrupted: unpredictable order.\n");
  1395. X    turnon(glob_flags, DO_UPDATE);
  1396. X    }
  1397. X    turnoff(glob_flags, IGN_SIGS);
  1398. X    off_intr();
  1399. X    /* Break pipes because message lists are invalid */
  1400. X    return 0 - in_pipe();
  1401. X}
  1402. X
  1403. X#ifdef MYQSORT
  1404. Xqsort(base, len, siz, compar)
  1405. Xregister struct msg *base;
  1406. Xint (*compar)();
  1407. X{
  1408. X     register int i, swapping;
  1409. X     struct msg temp;
  1410. X
  1411. X     do  {
  1412. X     swapping = 0;
  1413. X     for (i = 0; i < len-1; ++i) {
  1414. X         if (compar(base+i, base+i+1) > 0) {
  1415. X         temp = base[i];
  1416. X         base[i] = base[i+1];
  1417. X         base[i+1] = temp;
  1418. X         swapping = 1;
  1419. X         }
  1420. X     }
  1421. X     } while (swapping);
  1422. X}
  1423. X#endif /* MYSORT */
  1424. X
  1425. Xstatus_cmp(msg1, msg2)
  1426. Xregister struct msg *msg1, *msg2;
  1427. X{
  1428. X    if (ison(glob_flags, WAS_INTR))
  1429. X    longjmp(sortbuf, 1);
  1430. X    if (msg1 < msg || msg2 < msg) {
  1431. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1432. X    return 0;
  1433. X    }
  1434. X    if (msg1->m_flags == msg2->m_flags)
  1435. X        return 0;
  1436. X    if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
  1437. X    return order;
  1438. X    if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
  1439. X    return -order;
  1440. X    if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
  1441. X    return -order;
  1442. X    if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
  1443. X    return order;
  1444. X    if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
  1445. X    return -order;
  1446. X    if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
  1447. X    return order;
  1448. X    if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
  1449. X    return -order;
  1450. X    if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
  1451. X    return order;
  1452. X    if (ison(msg1->m_flags,REPLIED) && isoff(msg2->m_flags,REPLIED))
  1453. X    return -order;
  1454. X    if (isoff(msg1->m_flags,REPLIED) && ison(msg2->m_flags,REPLIED))
  1455. X    return order;
  1456. X    if (ison(msg1->m_flags,SAVED) && isoff(msg2->m_flags,SAVED))
  1457. X    return -order;
  1458. X    if (isoff(msg1->m_flags,SAVED) && ison(msg2->m_flags,SAVED))
  1459. X    return order;
  1460. X
  1461. X    return order;
  1462. X}
  1463. X
  1464. Xauthor_cmp(msg1, msg2)
  1465. Xregister struct msg *msg1, *msg2;
  1466. X{
  1467. X    char buf1[HDRSIZ], buf2[HDRSIZ];
  1468. X
  1469. X    if (ison(glob_flags, WAS_INTR))
  1470. X    longjmp(sortbuf, 1);
  1471. X    if (msg1 < msg || msg2 < msg) {
  1472. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1473. X    return 0;
  1474. X    }
  1475. X    (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
  1476. X    (void) reply_to(msg2 - msg, 0, buf2);
  1477. X    Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
  1478. X    if (ignore_case)
  1479. X    return lcase_strncmp(buf1, buf2, -1) * order;
  1480. X    return strcmp(buf1, buf2) * order;
  1481. X}
  1482. X
  1483. X/*
  1484. X * Subject comparison ignoring Re:  subject_to() appends an Re: if there is
  1485. X * any subject whatsoever.
  1486. X */
  1487. Xsubject_cmp(msg1, msg2)
  1488. Xregister struct msg *msg1, *msg2;
  1489. X{
  1490. X    char buf1[HDRSIZ], buf2[HDRSIZ];
  1491. X
  1492. X    if (ison(glob_flags, WAS_INTR))
  1493. X    longjmp(sortbuf, 1);
  1494. X    if (msg1 < msg || msg2 < msg) {
  1495. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1496. X    return 0;
  1497. X    }
  1498. X    (void) subject_to(msg1 - msg, buf1);
  1499. X    (void) subject_to(msg2 - msg, buf2);
  1500. X    Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg,buf1,msg2-msg,buf2);
  1501. X    if (ignore_case)
  1502. X    return lcase_strncmp(buf1, buf2, -1) * order;
  1503. X    return strcmp(buf1, buf2) * order;
  1504. X}
  1505. X
  1506. X/*
  1507. X * compare subject strings from two messages.
  1508. X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
  1509. X */
  1510. Xsubj_with_re(msg1, msg2)
  1511. Xregister struct msg *msg1, *msg2;
  1512. X{
  1513. X    char buf1[HDRSIZ], buf2[HDRSIZ], *p;
  1514. X
  1515. X    if (ison(glob_flags, WAS_INTR))
  1516. X    longjmp(sortbuf, 1);
  1517. X    if (msg1 < msg || msg2 < msg) {
  1518. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1519. X    return 0;
  1520. X    }
  1521. X    if (!(p = header_field(msg1 - msg, "subject")))
  1522. X    p = "";
  1523. X    (void) strcpy(buf1, p);
  1524. X    if (!(p = header_field(msg2 - msg, "subject")))
  1525. X    p = "";
  1526. X    (void) strcpy(buf2, p);
  1527. X    Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n",
  1528. X    msg1-msg, buf1, msg2-msg, buf2);
  1529. X    if (ignore_case)
  1530. X    return lcase_strncmp(buf1, buf2, -1) * order;
  1531. X    return strcmp(buf1, buf2) * order;
  1532. X}
  1533. X
  1534. Xdate_cmp(msg1, msg2)
  1535. Xregister struct msg *msg1, *msg2;
  1536. X{
  1537. X    if (ison(glob_flags, WAS_INTR))
  1538. X    longjmp(sortbuf, 1);
  1539. X    if (msg1 < msg || msg2 < msg) {
  1540. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1541. X    return 0;
  1542. X    }
  1543. X    if (ison(glob_flags, DATE_RECV))
  1544. X    return strcmp(msg1->m_date_recv, msg2->m_date_recv) * order;
  1545. X    else
  1546. X    return strcmp(msg1->m_date_sent, msg2->m_date_sent) * order;
  1547. X}
  1548. END_OF_FILE
  1549. if test 5803 -ne `wc -c <'sort.c'`; then
  1550.     echo shar: \"'sort.c'\" unpacked with wrong size!
  1551. fi
  1552. # end of 'sort.c'
  1553. fi
  1554. if test -f 'tool.c' -a "${1}" != "-c" ; then 
  1555.   echo shar: Will not clobber existing file \"'tool.c'\"
  1556. else
  1557. echo shar: Extracting \"'tool.c'\" \(4177 characters\)
  1558. sed "s/^X//" >'tool.c' <<'END_OF_FILE'
  1559. X/* @(#)tool.c    (c) copyright    10/15/86 (Dan Heller) */
  1560. X
  1561. X/* tool.c --make the mailtool windows, panels, etc... */
  1562. X#include "mush.h"
  1563. X
  1564. Xmake_tool(args)
  1565. Xchar **args;
  1566. X{
  1567. X    struct stat rootbuf, tmpbuf;
  1568. X    struct inputmask im;
  1569. X    register unsigned i;
  1570. X    char **choice_args, **button_args, *p;
  1571. X    char buf1[WIN_NAMESIZE], buf2[WIN_NAMESIZE];
  1572. X
  1573. X    getfonts();
  1574. X    mail_icon.ic_font = fonts[DEFAULT];
  1575. X
  1576. X    if (p = do_set(set_options, "screen_win"))
  1577. X    screen = atoi(p);
  1578. X    else
  1579. X    screen = 6;
  1580. X
  1581. X    /* where to place text on mail icon -- how many messages there are */
  1582. X    rect_construct(&mail_icon.ic_textrect,
  1583. X    l_width(DEFAULT), 58-l_height(DEFAULT),
  1584. X    3*l_width(DEFAULT), l_height(DEFAULT));
  1585. X
  1586. X    if (!(tool = tool_make(
  1587. X    WIN_ICON,         &mail_icon,
  1588. X    WIN_HEIGHT,         700,
  1589. X    WIN_WIDTH,         650,
  1590. X    WIN_BOUNDARY_MGR,     1,
  1591. X    WIN_ATTR_LIST,         args,
  1592. X    NULL)))
  1593. X    perror(prog_name), cleanup(0);
  1594. X    tool_free_attribute_list(args);
  1595. X
  1596. X    choice_args = panel_make_list(
  1597. X    PANEL_MENU_TITLE_FONT, fonts[LARGE],
  1598. X    PANEL_DISPLAY_LEVEL, PANEL_NONE,
  1599. X    PANEL_SHOW_MENU, TRUE,
  1600. X    PANEL_SHOW_MENU_MARK, FALSE,
  1601. X    0);
  1602. X
  1603. X    button_args = panel_make_list(
  1604. X    PANEL_FEEDBACK, PANEL_INVERTED,
  1605. X    PANEL_SHOW_MENU, FALSE,
  1606. X    0);
  1607. X
  1608. X    make_hdr_panel(choice_args, button_args);
  1609. X
  1610. X    if (!(hdr_sw = gfxsw_createtoolsubwindow(tool, "hdr_sw",
  1611. X    TOOL_SWEXTENDTOEDGE, 10+ screen*l_height(DEFAULT), (char **)0)))
  1612. X    perror("hdr_sw"), cleanup(0);
  1613. X    gfxsw_getretained((struct gfxsubwindow *)hdr_sw->ts_data);
  1614. X    hdr_win = ((struct gfxsubwindow *)(hdr_sw->ts_data))->gfx_pixwin;
  1615. X
  1616. X    input_imnull(&im);
  1617. X    win_setinputcodebit(&im, LOC_STILL);
  1618. X    win_setinputcodebit(&im, LOC_MOVE);
  1619. X    win_setinputcodebit(&im, LOC_WINENTER);
  1620. X    for (i = VKEY_FIRSTFUNC; i <= VKEY_LASTFUNC; i++)
  1621. X    win_setinputcodebit(&im, i);
  1622. X    win_setinputmask(hdr_sw->ts_windowfd, &im, &im,
  1623. X                   win_fdtonumber(hdr_panel_sw->ts_windowfd)); 
  1624. X    hdr_sw->ts_io.tio_selected = hdr_io;
  1625. X    hdr_sw->ts_io.tio_handlesigwinch = hdrwin_handlesigwinch;
  1626. X
  1627. X    make_main_panel(choice_args, button_args);
  1628. X    xfree(choice_args), xfree(button_args);
  1629. X
  1630. X    if (!(print_sw = gfxsw_createtoolsubwindow(tool, "print_sw",
  1631. X    TOOL_SWEXTENDTOEDGE, l_height(LARGE) + 10, (char **)0)))
  1632. X    perror("print_sw"), cleanup(0);
  1633. X    print_win = ((struct gfxsubwindow *)(print_sw->ts_data))->gfx_pixwin;
  1634. X    print_sw->ts_io.tio_handlesigwinch = print_sigwinch;
  1635. X
  1636. X    /* text subwindow */
  1637. X    if (!(msg_sw = gfxsw_createtoolsubwindow(tool, "msg_sw",
  1638. X    TOOL_SWEXTENDTOEDGE, TOOL_SWEXTENDTOEDGE, (char **)0)))
  1639. X    perror("msg_sw"), cleanup(0);
  1640. X    gfxsw_getretained((struct gfxsubwindow *)msg_sw->ts_data);
  1641. X    msg_win = ((struct gfxsubwindow *)(msg_sw->ts_data))->gfx_pixwin;
  1642. X
  1643. X    /* everything we want the text window to pay attention to */
  1644. X    input_imnull(&im);
  1645. X    im.im_flags = IM_ASCII;
  1646. X    im.im_flags &= ~IM_ANSI;
  1647. X    for (i = VKEY_FIRSTFUNC; i <= VKEY_LASTFUNC; i++)
  1648. X    win_setinputcodebit(&im, i);
  1649. X    win_setinputmask(msg_sw->ts_windowfd, &im, &im, WIN_NULLLINK);
  1650. X    msg_sw->ts_io.tio_selected = msg_io;
  1651. X    msg_sw->ts_io.tio_handlesigwinch = msgwin_handlesigwinch;
  1652. X
  1653. X    /* tty subwindow */
  1654. X    if (!(tty_sw = ttytlsw_createtoolsubwindow(tool, "tty_sw",
  1655. X    TOOL_SWEXTENDTOEDGE, 0, (char **)0)))
  1656. X    perror("tty_sw"), cleanup(0);
  1657. X    ttysw_handlesigwinch(tty_sw);
  1658. X    win_setcursor(tty_sw->ts_windowfd, &write_cursor);
  1659. X
  1660. X    (void) sprintf(blank, "%128c", ' ');
  1661. X    (void) signal(SIGWINCH, sigwinchcatcher);
  1662. X    (void) signal(SIGTERM, sigtermcatcher);
  1663. X    (void) signal(SIGCHLD, sigchldcatcher);
  1664. X    pw_writebackground(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,
  1665. X               PIX_CLR);
  1666. X    if (ioctl(0, TIOCGETC, &tchars))
  1667. X    perror("gtty failed"), cleanup(0);
  1668. X    win_numbertoname (0, buf1);
  1669. X    if ((rootfd = open(buf1, 0)) == -1)
  1670. X    error("can't open %s", buf1), cleanup(0);
  1671. X    if (fstat(rootfd, &rootbuf))
  1672. X    error("can't stat %s", buf1), cleanup(0);
  1673. X    for (parentfd = 3; parentfd < rootfd; parentfd++)
  1674. X    if (fstat(parentfd, &tmpbuf))
  1675. X        error("Can't stat fd-%d", parentfd);
  1676. X    else if (tmpbuf.st_ino == rootbuf.st_ino) {
  1677. X        (void) close(rootfd);
  1678. X        rootfd = parentfd;
  1679. X        break;
  1680. X    }
  1681. X    istool = 2;
  1682. X    (void) do_version();
  1683. X    lock_cursors();
  1684. X    tool_install(tool);
  1685. X    tool_display(tool);
  1686. X    do_clear();
  1687. X}
  1688. END_OF_FILE
  1689. if test 4177 -ne `wc -c <'tool.c'`; then
  1690.     echo shar: \"'tool.c'\" unpacked with wrong size!
  1691. fi
  1692. # end of 'tool.c'
  1693. fi
  1694. echo shar: End of archive 3 \(of 19\).
  1695. cp /dev/null ark3isdone
  1696. MISSING=""
  1697. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1698.     if test ! -f ark${I}isdone ; then
  1699.     MISSING="${MISSING} ${I}"
  1700.     fi
  1701. done
  1702. if test "${MISSING}" = "" ; then
  1703.     echo You have unpacked all 19 archives.
  1704.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1705. else
  1706.     echo You still need to unpack the following archives:
  1707.     echo "        " ${MISSING}
  1708. fi
  1709. ##  End of shell archive.
  1710. exit 0
  1711.